home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PRINTER
/
JPSRC11.ARJ
/
JETFONT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-08-03
|
21KB
|
674 lines
/*
* JET PAK - HP DeskJet and LaserJet series printer utilities
*
* JETFONT module - soft font utility functions
*
* Version 1.1 (Public Domain)
*/
/* system include files */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* application include files */
#include "jetfont.h"
#include "jetutil.h"
/*
* LOCAL DEFINITIONS
*/
/* macros for byte/word i/o */
#define byte_read(nb,fp,dst) \
if (do_byte_read(&nb, fp, &dst) == ERROR) \
return(ERROR);
#define int_read(nb,fp,dst) \
if (do_int_read(&nb, fp, &dst) == ERROR) \
return(ERROR);
#define byte_write(fp,src) \
if (do_byte_write(fp, src) == ERROR) \
return(ERROR);
#define int_write(fp,src) \
if (do_int_write(fp, src) == ERROR) \
return(ERROR);
/* Descriptor readers and writers */
static int font_descriptor_read();
static int character_code_read();
static int character_descriptor_read();
static int font_descriptor_write();
static int character_code_write();
static int character_descriptor_write();
/* Low level readers and writers */
static int do_byte_read();
static int do_int_read();
static int do_byte_write();
static int do_int_write();
/* Command -> handler function mapping table */
static struct {
int type;
char *start;
char *end;
int (*reader)();
int (*writer)();
} command_table[] = {
{ FDC,FDC_S,FDC_E,font_descriptor_read,font_descriptor_write },
{ CCC,CCC_S,CCC_E,character_code_read,character_code_write },
{ CDC,CDC_S,CDC_E,character_descriptor_read,character_descriptor_write },
};
/*
* FONT COMMAND I/O
*/
int font_command_read(infp, fcp)
FILE *infp;
FONT_COMMAND *fcp;
{
/*
* Read an arbitrary font command from infp. Any characters up to
* the first ESC are silently consumed. If a command is recognised
* a lower level handler is called to read in the descriptor. If
* an unrecognised command is encountered, a warning is given.
*/
int r, i;
char esc_start[11], esc_end[2];
int (*reader)(); /* for brain-damaged compilers */
do
{
/* skip junk between escape sequences (eg NULs are occasionally
found in badly constructed fonts) */
do
{
if ((r = getc(infp)) == EOF)
return(EOF);
} while (r != '\033');
/* read a PCL style escape sequence */
if ((r = fscanf(infp, "%10[^+-0123456789]%d%1s",
esc_start, &fcp->number, esc_end)) == 3)
{
for (i = 0; i < sizeofarray(command_table); i++)
{
if ( (strcmp(esc_start, command_table[i].start) == 0)
&& (strcmp(esc_end , command_table[i].end ) == 0) )
{
fcp->command_type = command_table[i].type;
reader = command_table[i].reader;
r = (*reader)(infp, fcp);
/* normal return point */
return(r);
}
}
/* this is needed because a few soft fonts include arbitrary
printer escape sequences that aren't really part of the soft
font (eg OE18R#US.SFP and SC18R#US.SFP) */
fprintf(stderr, WARNING_COMMAND_SKIPPED, os_dir, os_file,
esc_start, fcp->number, esc_end);
}
} while (r == 3);
/* EOF (normally) or unexpected printer escape sequence structure */
if (r != EOF)
r = ERROR;
return(r);
}
int font_command_write(outfp, fcp)
FILE *outfp;
FONT_COMMAND *fcp;
{
/*
* Write an arbitrary font command to outfp. The generic part of
* the escape sequence is output first. Then a lower level handler
* is called to output the remainder of the escape sequence, which
* is specific to the actual command.
*/
int r, i;
int (*writer)(); /* for brain-damaged compilers */
for (i = 0; i < sizeofarray(command_table); i++)
{
if (fcp->command_type == command_table[i].type)
{
if ((r = fprintf(outfp, "\033%s%d%1s", command_table[i].start,
fcp->number, command_table[i].end)) > 0)
{
writer = command_table[i].writer;
r = (*writer)(outfp, fcp);
}
else
{
r = ERROR;
}
break;
}
}
return(r);
}
static int font_descriptor_read(infp, fcp)
FILE *infp;
FONT_COMMAND *fcp;
{
/*
* Read a font descriptor. This is a fairly complicated as there
* are several data sizes to deal with: the routine is passed an
* overall data size read in as part of the command. The
* descriptor(s) themselves include another data size.
*
* The difference between the command data size(s) and the sum of
* the descriptor sizes is accounted for by comment bytes.
* Although the kosher descriptor size for an LJ soft font is 64,
* many fonts put in a lower value.
*/
int i, nc = 0, nd = fcp->number;
UNSIGNEDBYTE temp_byte;
char junk;
int_read(nd, infp, fcp->data.font.size);
/* split byte count into data bytes and other bytes */
if (fcp->data.font.size < 2)
{
/* this should never occur in practice */
nc = nd;
nd = 0;
}
else if (fcp->data.font.size < (nd + 2))
{
nc = (nd + 2) - fcp->data.font.size;
nd -= nc;
}
byte_read(nd, infp, fcp->data.font.header_format);
byte_read(nd, infp, fcp->data.font.type);
int_read(nd, infp, fcp->data.font.reserved1);
int_read(nd, infp, fcp->data.font.baseline_distance);
int_read(nd, infp, fcp->data.font.cell_width);
int_read(nd, infp, fcp->data.font.cell_height);
byte_read(nd, infp, fcp->data.font.orientation);
byte_read(nd, infp, fcp->data.font.spacing);
int_read(nd, infp, fcp->data.font.symbol_set);
int_read(nd, infp, fcp->data.font.pitch);
int_read(nd, infp, fcp->data.font.height);
int_read(nd, infp, fcp->data.font.x_height);
byte_read(nd, infp, fcp->data.font.width_type);
if (fcp->data.font.header_format == DJ500FONTFORMAT)
{
int_read(nd, infp, fcp->data.font.style);
}
else
{
byte_read(nd, infp, temp_byte);
fcp->data.font.style = (UNSIGNEDINT)temp_byte;
}
byte_read(nd, infp, fcp->data.font.stroke_weight);
if (fcp->data.font.header_format == DJ500FONTFORMAT)
{
int_read(nd, infp, fcp->data.font.typeface);
}
else
{
byte_read(nd, infp, temp_byte);
fcp->data.font.typeface = (UNSIGNEDINT)temp_byte;
}
byte_read(nd, infp, fcp->data.font.slant);
byte_read(nd, infp, fcp->data.font.serif_style);
byte_read(nd, infp, fcp->data.font.quality);
byte_read(nd, infp, fcp->data.font.placement);
byte_read(nd, infp, fcp->data.font.underline_distance);
byte_read(nd, infp, fcp->data.font.underline_height);
int_read(nd, infp, fcp->data.font.text_height);
int_read(nd, infp, fcp->data.font.text_width);
int_read(nd, infp, fcp->data.font.first_code);
int_read(nd, infp, fcp->data.font.last_code);
byte_read(nd, infp, fcp->data.font.pitch_extended);
byte_read(nd, infp, fcp->data.font.height_extended);
int_read(nd, infp, fcp->data.font.reserved2);
int_read(nd, infp, fcp->data.font.font_number_top);
int_read(nd, infp, fcp->data.font.font_number_bot);
for (i = 0; i < sizeof(fcp->data.font.name); i++)
{
byte_read(nd, infp, fcp->data.font.name[i]);
if (fcp->data.font.name[i] == '\0')
fcp->data.font.name[i] = ' ';
}
/* this is the DJ specific stuff in the standard header */
int_read(nd, infp, fcp->data.font.h_pixel_resolution);
int_read(nd, infp, fcp->data.font.v_pixel_resolution);
byte_read(nd, infp, fcp->data.font.tdu_distance);
byte_read(nd, infp, fcp->data.font.tdu_height);
byte_read(nd, infp, fcp->data.font.bdu_distance);
byte_read(nd, infp, fcp->data.font.bdu_height);
/* read a printer specific block: this is usually present in
DJ soft fonts but not in any of the LJ soft fonts I have seen.
This test gets around the problem that many LJ fonts will often
have a garbage value (ie comment stuff) where you should get a
descriptor size. If all the data up to the printer specific
block is present, chances are it's OK to go ahead and
try to read a printer specific block */
if (fcp->data.font.size >= DJFDSIZE)
{
/* lump byte counts together again */
nd += nc;
nc = 0;
int_read(nd, infp, fcp->data.font.specific_size);
/* split byte count into data bytes and other bytes */
if (fcp->data.font.specific_size < 2)
{
/* this does occur - the fonts in Elfring Soft Fonts'
DJETFONT.ZIP package have a printer specific block
size of 0 */
nc = nd;
nd = 0;
}
else if (fcp->data.font.specific_size < (nd + 2))
{
nc = (nd + 2) - fcp->data.font.specific_size;
nd -= nc;
}
int_read(nd, infp, fcp->data.font.data_size);
byte_read(nd, infp, fcp->data.font.unidirection);
byte_read(nd, infp, fcp->data.font.compressed);
byte_read(nd, infp, fcp->data.font.hold_time_factor);
byte_read(nd, infp, fcp->data.font.no_half_pitch);
byte_read(nd, infp, fcp->data.font.no_double_pitch);
byte_read(nd, infp, fcp->data.font.no_half_height);
byte_read(nd, infp, fcp->data.font.no_bold);
byte_read(nd, infp, fcp->data.font.no_draft);
byte_read(nd, infp, fcp->data.font.bold_method);
byte_read(nd, infp, fcp->data.font.reserved3);
int_read(nd, infp, fcp->data.font.baseline_offset_2);
int_read(nd, infp, fcp->data.font.baseline_offset_3);
int_read(nd, infp, fcp->data.font.baseline_offset_4);
if (fcp->data.font.specific_size >= DJ500SSIZE)
{
for (i = 0; i < sizeof(fcp->data.font.name_extension); i++)
{
byte_read(nd, infp, fcp->data.font.name_extension[i]);
if (fcp->data.font.name_extension[i] == '\0')
fcp->data.font.name_extension[i] = ' ';
}
}
}
/* any remaining bytes are comments */
for (i = 0; i < COMMENT_SIZE_MAX-1 && nc > 0; i++)
{
byte_read(nc, infp, fcp->data.font.comment[i]);
if (fcp->data.font.comment[i] == '\0')
fcp->data.font.comment[i] = ' ';
}
fcp->data.font.comment[i] = '\0';
/* if nc > 0 here, you ran out of space in the comment string */
while (nc > 0)
byte_read(nc, infp, junk);
return(OK);
}
static int font_descriptor_write(outfp, fcp)
FILE *outfp;
FONT_COMMAND *fcp;
{
/*
* Write a font descriptor. Compared to reading one, this is a
* cinch.
*/
int i, len;
int_write(outfp, fcp->data.font.size);
byte_write(outfp, fcp->data.font.header_format);
byte_write(outfp, fcp->data.font.type);
int_write(outfp, fcp->data.font.reserved1);
int_write(outfp, fcp->data.font.baseline_distance);
int_write(outfp, fcp->data.font.cell_width);
int_write(outfp, fcp->data.font.cell_height);
byte_write(outfp, fcp->data.font.orientation);
byte_write(outfp, fcp->data.font.spacing);
int_write(outfp, fcp->data.font.symbol_set);
int_write(outfp, fcp->data.font.pitch);
int_write(outfp, fcp->data.font.height);
int_write(outfp, fcp->data.font.x_height);
byte_write(outfp, fcp->data.font.width_type);
if (fcp->data.font.header_format == DJ500FONTFORMAT)
{
int_write(outfp, fcp->data.font.style);
}
else
{
byte_write(outfp, (UNSIGNEDBYTE)fcp->data.font.style);
}
byte_write(outfp, fcp->data.font.stroke_weight);
if (fcp->data.font.header_format == DJ500FONTFORMAT)
{
int_write(outfp, fcp->data.font.typeface);
}
else
{
byte_write(outfp, (UNSIGNEDBYTE)fcp->data.font.typeface);
}
byte_write(outfp, fcp->data.font.slant);
byte_write(outfp, fcp->data.font.serif_style);
byte_write(outfp, fcp->data.font.quality);
byte_write(outfp, fcp->data.font.placement);
byte_write(outfp, fcp->data.font.underline_distance);
byte_write(outfp, fcp->data.font.underline_height);
int_write(outfp, fcp->data.font.text_height);
int_write(outfp, fcp->data.font.text_width);
int_write(outfp, fcp->data.font.first_code);
int_write(outfp, fcp->data.font.last_code);
byte_write(outfp, fcp->data.font.pitch_extended);
byte_write(outfp, fcp->data.font.height_extended);
int_write(outfp, fcp->data.font.reserved2);
int_write(outfp, fcp->data.font.font_number_top);
int_write(outfp, fcp->data.font.font_number_bot);
for (i = 0; i < sizeof(fcp->data.font.name); i++)
byte_write(outfp, fcp->data.font.name[i]);
if (fcp->data.font.size >= DJFDSIZE)
{
int_write(outfp, fcp->data.font.h_pixel_resolution);
int_write(outfp, fcp->data.font.v_pixel_resolution);
byte_write(outfp, fcp->data.font.tdu_distance);
byte_write(outfp, fcp->data.font.tdu_height);
byte_write(outfp, fcp->data.font.bdu_distance);
byte_write(outfp, fcp->data.font.bdu_height);
int_write(outfp, fcp->data.font.specific_size);
int_write(outfp, fcp->data.font.data_size);
byte_write(outfp, fcp->data.font.unidirection);
byte_write(outfp, fcp->data.font.compressed);
byte_write(outfp, fcp->data.font.hold_time_factor);
byte_write(outfp, fcp->data.font.no_half_pitch);
byte_write(outfp, fcp->data.font.no_double_pitch);
byte_write(outfp, fcp->data.font.no_half_height);
byte_write(outfp, fcp->data.font.no_bold);
byte_write(outfp, fcp->data.font.no_draft);
byte_write(outfp, fcp->data.font.bold_method);
byte_write(outfp, fcp->data.font.reserved3);
int_write(outfp, fcp->data.font.baseline_offset_2);
int_write(outfp, fcp->data.font.baseline_offset_3);
int_write(outfp, fcp->data.font.baseline_offset_4);
if (fcp->data.font.specific_size >= DJ500SSIZE)
{
for (i = 0; i < sizeof(fcp->data.font.name_extension); i++)
byte_write(outfp, fcp->data.font.name_extension[i]);
}
}
if ((len = strlen(fcp->data.font.comment)) > 0)
if (fwrite(fcp->data.font.comment, 1, len, outfp) != len)
return(ERROR);
return(OK);
}
static int character_code_read(infp, fcp)
FILE *infp;
FONT_COMMAND *fcp;
{
/*
* Nothing to do here as the character code command doesn't have
* an associated descriptor
*/
return(OK);
}
static int character_code_write(outfp, fcp)
FILE *outfp;
FONT_COMMAND *fcp;
{
/*
* Nothing to do here as the character code command doesn't have
* an associated descriptor
*/
return(OK);
}
static int character_descriptor_read(infp, fcp)
FILE *infp;
FONT_COMMAND *fcp;
{
/*
* Read a character descriptor. Fortunately character descriptors
* don't seem to have comments. Half-way through reading the
* descriptor you discover which kind you're dealing with and
* switch to different code for each.
*/
int nd = fcp->number;
struct ljchar_struct *ljcp;
struct djchar_struct *djcp;
byte_read(nd, infp, fcp->data.character.format);
byte_read(nd, infp, fcp->data.character.continuation);
switch(fcp->data.character.format)
{
default:
case LJCHARFORMAT:
ljcp = &fcp->data.character.data.ljchar;
byte_read(nd, infp, ljcp->descriptor_size);
byte_read(nd, infp, ljcp->class);
byte_read(nd, infp, ljcp->orientation);
byte_read(nd, infp, ljcp->reserved);
int_read(nd, infp, ljcp->left_offset);
int_read(nd, infp, ljcp->top_offset);
int_read(nd, infp, ljcp->character_width);
int_read(nd, infp, ljcp->character_height);
int_read(nd, infp, ljcp->delta_x);
if (nd > BITMAP_SIZE_MAX)
return(ERROR);
if (fread(ljcp->bitmap, 1, nd, infp) != nd)
return(ERROR);
break;
case DJCHARFORMAT:
case DJPCHARFORMAT:
case DJ500CHARFORMAT:
djcp = &fcp->data.character.data.djchar;
byte_read(nd, infp, djcp->descriptor_size);
byte_read(nd, infp, djcp->char_type);
byte_read(nd, infp, djcp->character_width);
byte_read(nd, infp, djcp->comp_width);
byte_read(nd, infp, djcp->left_offset);
byte_read(nd, infp, djcp->right_offset);
if (nd > BITMAP_SIZE_MAX)
return(ERROR);
if (fread(djcp->bitmap, 1, nd, infp) != nd)
return(ERROR);
break;
}
return(OK);
}
static int character_descriptor_write(outfp, fcp)
FILE *outfp;
FONT_COMMAND *fcp;
{
/*
* Write a character descriptor.
*/
int nd = fcp->number;
struct ljchar_struct *ljcp;
struct djchar_struct *djcp;
byte_write(outfp, fcp->data.character.format);
byte_write(outfp, fcp->data.character.continuation);
switch(fcp->data.character.format)
{
default:
case LJCHARFORMAT:
ljcp = &fcp->data.character.data.ljchar;
byte_write(outfp, ljcp->descriptor_size);
byte_write(outfp, ljcp->class);
byte_write(outfp, ljcp->orientation);
byte_write(outfp, ljcp->reserved);
int_write(outfp, ljcp->left_offset);
int_write(outfp, ljcp->top_offset);
int_write(outfp, ljcp->character_width);
int_write(outfp, ljcp->character_height);
int_write(outfp, ljcp->delta_x);
nd -= (2 + ljcp->descriptor_size);
if (fwrite(ljcp->bitmap, 1, nd, outfp) != nd)
return(ERROR);
break;
case DJCHARFORMAT:
case DJPCHARFORMAT:
case DJ500CHARFORMAT:
djcp = &fcp->data.character.data.djchar;
byte_write(outfp, djcp->descriptor_size);
byte_write(outfp, djcp->char_type);
byte_write(outfp, djcp->character_width);
byte_write(outfp, djcp->comp_width);
byte_write(outfp, djcp->left_offset);
byte_write(outfp, djcp->right_offset);
nd -= (2 + djcp->descriptor_size);
if (fwrite(djcp->bitmap, 1, nd, outfp) != nd)
return(ERROR);
break;
}
return(OK);
}
/*
* LOW LEVEL I/O
*/
static int do_byte_read(nbp, fp, dp)
int *nbp;
FILE *fp;
UNSIGNEDBYTE *dp;
{
/*
* If there's enough data available, read a byte, checking for
* errors.
*/
int wrk;
if ((*nbp -=1) < 0)
*dp = 0;
else if ((wrk = getc(fp)) == EOF)
return(ERROR);
else
*dp = wrk;
return(OK);
}
static int do_int_read(nbp, fp, dp)
int *nbp;
FILE *fp;
UNSIGNEDINT *dp;
{
/*
* If there's enough data available, read a word, checking for
* errors.
*/
int wrk;
if ((*nbp -= 2) < 0)
*dp = 0;
else
{
if ((wrk = getc(fp)) == EOF)
return(ERROR);
*dp = (wrk << 8);
if ((wrk = getc(fp)) == EOF)
return(ERROR);
*dp |= wrk;
}
return(OK);
}
static int do_byte_write(fp, src)
FILE *fp;
UNSIGNEDBYTE src;
{
/*
* Write a byte, checking for errors
*/
if (putc(src, fp) == EOF)
return(ERROR);
return(OK);
}
static int do_int_write(fp, src)
FILE *fp;
UNSIGNEDINT src;
{
/*
* Write a word, checking for errors
*/
if (putc(src>>8,fp) == EOF)
return(ERROR);
if (putc(src&0xff,fp) == EOF)
return(ERROR);
return(OK);
}